#include "QHVlcPlayer.h"

#include <QDebug>
#include <QFile>

#include "vlc_common.h"
#include "vlc_fourcc.h"

static void handleEvents(const libvlc_event_t *event, void *userData)
{
    QHVlcPlayer *obj = (QHVlcPlayer*)userData;

    switch (event->type)
    {
    case libvlc_MediaPlayerPositionChanged:
    {
        emit obj->signalPositonChanged(event->u.media_player_position_changed.new_position);
        break;
    }
    case libvlc_MediaPlayerTimeChanged:
    {
        emit obj->signalTimeChanged(event->u.media_player_time_changed.new_time);
        break;
    }
    case libvlc_MediaPlayerPlaying:
    {
        emit obj->signalMediaPlaying();
        break;
    }
    case libvlc_MediaPlayerEncounteredError:
    {
        emit obj->signalMediaError();
        break;
    }
    default:
        break;
    }
}

QHVlcPlayer::QHVlcPlayer(QObject *parent)
    : QObject(parent)
    , m_vlcInstance(nullptr)
    , m_media(nullptr)
    , m_vlcMediaPlayer(nullptr)
    , m_vlcEventManager(nullptr)
{

}

QHVlcPlayer::~QHVlcPlayer()
{
    release();
}

int QHVlcPlayer::screenshot(const QString &name)
{
    if(m_vlcMediaPlayer)
    {
        return  libvlc_video_take_snapshot(m_vlcMediaPlayer,0,name.toStdString().data(),0,0);
    }
    return -1;
}

void QHVlcPlayer::setLocalFile(const QString &fileName,void *hwnd)
{
    if (!QFile::exists(fileName))
    {
        return;
    }

    release();

    m_vlcInstance=libvlc_new(0, nullptr);

    const char *vlc_args[] = {
        "--avcodec-codec=auto"  // 默认使用自动选择解码器
    };

    m_media=libvlc_media_new_path(m_vlcInstance, fileName.toUtf8().data());
    if(m_media)
    {
        // 解析媒体
        libvlc_media_parse(m_media);

        // 获取媒体信息
        libvlc_media_track_t **tracks;
        unsigned int track_count = libvlc_media_tracks_get(m_media, &tracks);

        for (unsigned int i = 0; i < track_count; ++i) {
            if (tracks[i]->i_type == libvlc_track_video) {
                // 获取视频编码类型
                uint32_t codec = tracks[i]->i_codec;
                switch (codec) {
                    case VLC_CODEC_H264:
                        vlc_args[0] = "--avcodec-codec=h264_mxvid";
                        break;
                    case VLC_CODEC_HEVC:
                        vlc_args[0] = "--avcodec-codec=hevc_mxvid";
                        break;
                    case VLC_CODEC_AV1:
                        vlc_args[0] = "--avcodec-codec=av1_mxvid";
                        break;
                    default:
                        break;
                }
                break;
            }
        }

        qDebug()<<"got codec options: "<<vlc_args[0];

        // 释放媒体信息
        libvlc_media_tracks_release(tracks, track_count);

        // 重新创建 VLC 实例并传递参数
        libvlc_release(m_vlcInstance);

        m_vlcInstance = libvlc_new(1, vlc_args);
        if (!m_vlcInstance) {
            qDebug() << "Failed to create VLC instance with codec parameters";
            return;
        }

        // 重新创建媒体对象
        libvlc_media_release(m_media);
        m_media = libvlc_media_new_path(m_vlcInstance, fileName.toUtf8().data());
        if (!m_media) {
            //freeVlc();
            return;
        }

        m_vlcMediaPlayer = libvlc_media_player_new_from_media(m_media);
        if(m_vlcMediaPlayer)
        {
            m_vlcEventManager = libvlc_media_player_event_manager(m_vlcMediaPlayer);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerPositionChanged,handleEvents,this);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerTimeChanged,handleEvents,this);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerPlaying,handleEvents,this);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerEncounteredError,handleEvents,this);

            if(hwnd != nullptr)
            {
                //libvlc_media_player_set_hwnd(m_vlcMediaPlayer,hwnd);
#ifdef Q_OS_WIN
                libvlc_media_player_set_hwnd(m_vlcMediaPlayer, hwnd);
#elif defined(Q_OS_LINUX)
                libvlc_media_player_set_xwindow(m_vlcMediaPlayer, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(hwnd)));
#elif defined(Q_OS_MAC)
                libvlc_media_player_set_nsobject(m_vlcMediaPlayer, hwnd);
#endif
            }
        }
    }
}

void QHVlcPlayer::setUrl(const QString &url,void *hwnd)
{
    m_url=url;
    release();
    m_vlcInstance=libvlc_new(0, nullptr);
    m_media=libvlc_media_new_location(m_vlcInstance, m_url.toUtf8().data());
    if(m_media)
    {
        const char *vlc_args[] = {
            "--avcodec-codec=auto"  // 默认使用自动选择解码器
        };

        // 解析媒体
        libvlc_media_parse(m_media);

        // 获取媒体信息
        libvlc_media_track_t **tracks;
        unsigned int track_count = libvlc_media_tracks_get(m_media, &tracks);

        for (unsigned int i = 0; i < track_count; ++i) {
            if (tracks[i]->i_type == libvlc_track_video) {
                // 获取视频编码类型
                uint32_t codec = tracks[i]->i_codec;
                switch (codec) {
                    case VLC_CODEC_H264:
                        vlc_args[0] = "--avcodec-codec=h264_mxvid";
                        break;
                    case VLC_CODEC_HEVC:
                        vlc_args[0] = "--avcodec-codec=hevc_mxvid";
                        break;
                    case VLC_CODEC_AV1:
                        vlc_args[0] = "--avcodec-codec=av1_mxvid";
                        break;
                    default:
                        break;
                }
                break;
            }
        }

        qDebug()<<"got codec options: "<<vlc_args[0];
        exit(0);

        // 释放媒体信息
        libvlc_media_tracks_release(tracks, track_count);

        // 重新创建 VLC 实例并传递参数
        libvlc_release(m_vlcInstance);

        m_vlcInstance = libvlc_new(1, vlc_args);
        if (!m_vlcInstance) {
            qDebug() << "Failed to create VLC instance with codec parameters";
            return;
        }

        // 重新创建媒体对象
        libvlc_media_release(m_media);
        m_media = libvlc_media_new_location(m_vlcInstance, m_url.toUtf8().data());
        if (!m_media) {
            //freeVlc();
            return;
        }

        libvlc_media_add_option(m_media, ":network-caching=1000");
        m_vlcMediaPlayer = libvlc_media_player_new_from_media(m_media);
        if(m_vlcMediaPlayer)
        {
            m_vlcEventManager = libvlc_media_player_event_manager(m_vlcMediaPlayer);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerPositionChanged,handleEvents,this);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerTimeChanged,handleEvents,this);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerPlaying,handleEvents,this);
            libvlc_event_attach(m_vlcEventManager,libvlc_MediaPlayerEncounteredError,handleEvents,this);

            if(hwnd != nullptr)
            {
                //libvlc_media_player_set_hwnd(m_vlcMediaPlayer,hwnd);
#ifdef Q_OS_WIN
                libvlc_media_player_set_hwnd(m_vlcMediaPlayer, hwnd);
#elif defined(Q_OS_LINUX)
                libvlc_media_player_set_xwindow(m_vlcMediaPlayer, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(hwnd)));
#elif defined(Q_OS_MAC)
                libvlc_media_player_set_nsobject(m_vlcMediaPlayer, hwnd);
#endif
            }
        }
    }
}

int QHVlcPlayer::play()
{
    if(m_vlcMediaPlayer)
    {
        if(getPlayState() != libvlc_Playing)
        {
            return  libvlc_media_player_play(m_vlcMediaPlayer);
        }
    }
    return -1;
}

void QHVlcPlayer::pause()
{
    if(m_vlcMediaPlayer)
    {
        if(getPlayState() != libvlc_Paused)
        {
            libvlc_media_player_pause(m_vlcMediaPlayer);
        }
    }
}

void QHVlcPlayer::stop()
{
    if(m_vlcMediaPlayer)
    {
        if(getPlayState() != libvlc_Ended)
        {
            libvlc_media_player_pause(m_vlcMediaPlayer);
            libvlc_media_player_stop(m_vlcMediaPlayer);
        }
    }
}

void QHVlcPlayer::setMute(bool value)
{
    if(m_vlcMediaPlayer)
    {
        libvlc_audio_set_mute(m_vlcMediaPlayer,value);
    }
}

void QHVlcPlayer::setVolume(int value)
{
    if(m_vlcMediaPlayer)
    {
        libvlc_audio_set_volume(m_vlcMediaPlayer,value);
    }
}

int QHVlcPlayer::getVolume()
{
    if(m_vlcMediaPlayer)
    {
        return libvlc_audio_get_volume(m_vlcMediaPlayer);
    }
    return 0;
}

void QHVlcPlayer::seekTo(float value)
{
    if(m_vlcMediaPlayer)
    {
        libvlc_media_player_set_position(m_vlcMediaPlayer, value);
    }
}

bool QHVlcPlayer::isOpen()
{
    return nullptr != m_vlcMediaPlayer;
}

bool QHVlcPlayer::isPlaying()
{
    if(m_vlcMediaPlayer)
    {
        return libvlc_media_player_is_playing(m_vlcMediaPlayer);
    }
    return false;
}

bool QHVlcPlayer::isPause()
{
    bool temp=false;
    if(m_vlcMediaPlayer)
    {
        int state = libvlc_media_player_get_state(m_vlcMediaPlayer);
        switch (state)
        {
        case libvlc_Paused:
        case libvlc_Stopped:
            temp = true;
            break;
        default:
            break;
        }
    }
    return temp;
}

long long QHVlcPlayer::getTotalTime()
{
    if(m_vlcMediaPlayer)
    {
        return libvlc_media_player_get_length(m_vlcMediaPlayer);
    }

    return 0;
}

int QHVlcPlayer::getPlayState()
{
    if(m_vlcMediaPlayer)
    {
        return libvlc_media_player_get_state(m_vlcMediaPlayer);
    }
    return -1;
}

void QHVlcPlayer::release()
{
    stop();
    if(m_vlcMediaPlayer)
    {
        libvlc_media_player_stop(m_vlcMediaPlayer);
        libvlc_media_player_release(m_vlcMediaPlayer);
        m_vlcMediaPlayer = nullptr;

    }

    if(m_media)
    {
        libvlc_media_release(m_media);
        m_media = nullptr;
    }

    if(m_vlcInstance)
    {
        libvlc_release(m_vlcInstance);
        m_vlcInstance = nullptr;
    }
}

